/*
 * Copyright (c) 2020 - present, Inspur Genersoft Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

package com.inspur.edp.lcm.metadata.core;

import com.inspur.edp.jittojava.context.GenerateService;
import com.inspur.edp.lcm.maven.utils.MavenInvoker;
import com.inspur.edp.lcm.metadata.api.entity.ApiModuleInfo;
import com.inspur.edp.lcm.metadata.api.entity.GspMetadata;
import com.inspur.edp.lcm.metadata.api.entity.GspProject;
import com.inspur.edp.lcm.metadata.api.entity.MetadataCompilerContext;
import com.inspur.edp.lcm.metadata.api.entity.MetadataPackage;
import com.inspur.edp.lcm.metadata.api.entity.MetadataPackageHeader;
import com.inspur.edp.lcm.metadata.api.entity.MetadataPackageVersion;
import com.inspur.edp.lcm.metadata.api.entity.MetadataProject;
import com.inspur.edp.lcm.metadata.api.entity.ProcessMode;
import com.inspur.edp.lcm.metadata.api.entity.ProjectHeader;
import com.inspur.edp.lcm.metadata.api.exception.ErrorCodes;
import com.inspur.edp.lcm.metadata.api.exception.LcmMavenDevException;
import com.inspur.edp.lcm.metadata.api.exception.LcmMetadataDevException;
import com.inspur.edp.lcm.metadata.api.i18n.LcmMetadataDevLog;
import com.inspur.edp.lcm.metadata.api.i18n.LogCodes;
import com.inspur.edp.lcm.metadata.api.mvnEntity.MavenComponent;
import com.inspur.edp.lcm.metadata.api.mvnEntity.MavenComponents;
import com.inspur.edp.lcm.metadata.api.mvnEntity.MavenPackageRefs;
import com.inspur.edp.lcm.metadata.api.mvnEntity.MetadataInfoInMaven;
import com.inspur.edp.lcm.metadata.api.mvnEntity.MetadataRepo;
import com.inspur.edp.lcm.metadata.api.mvnEntity.PackageSourceDto;
import com.inspur.edp.lcm.metadata.api.mvnEntity.PackageWithMetadataInfo;
import com.inspur.edp.lcm.metadata.api.mvnEntity.withprocessmode.MavenPackageRefWithProcessMode;
import com.inspur.edp.lcm.metadata.common.FileServiceImp;
import com.inspur.edp.lcm.metadata.common.MavenUtils;
import com.inspur.edp.lcm.metadata.common.Utils;
import com.inspur.edp.lcm.metadata.core.entity.MdProjectDependencyNode;
import com.inspur.edp.lcm.metadata.core.entity.MdprojInfoDto;
import com.inspur.edp.lcm.metadata.core.entity.PackageType;
import com.inspur.edp.lcm.metadata.core.extend.MavenAfterCompileActionImpl;
import com.inspur.edp.lcm.metadata.core.extend.MavenBeforeCompileActionImpl;
import com.inspur.edp.lcm.metadata.core.index.MetadataPackageIndexService;
import com.inspur.edp.lcm.metadata.core.manager.IndexServerManager;
import com.inspur.edp.lcm.metadata.core.manager.MavenCommandGenerator;
import com.inspur.edp.lcm.metadata.core.manager.MavenDeploymentForMdpkgManager;
import com.inspur.edp.lcm.metadata.core.manager.PackageNameManager;
import com.inspur.edp.lcm.metadata.core.manager.PomManager;
import com.inspur.edp.lcm.metadata.core.manager.VersionManager;
import com.inspur.edp.lcm.metadata.core.persistence.RepositoryFactory;
import com.inspur.edp.lcm.metadata.core.sync.CopyToPackagesRunnable;
import com.inspur.edp.lcm.metadata.core.sync.InstallJarRunnable;
import com.inspur.edp.lcm.metadata.core.sync.InstallSingleJarRunnable;
import com.inspur.edp.lcm.metadata.core.util.MdpkgUtils;
import com.inspur.edp.lcm.metadata.inner.api.IdeLogService;
import com.inspur.edp.lcm.metadata.inner.api.IdeSettingService;
import com.inspur.edp.lcm.metadata.inner.api.data.MavenMirror;
import com.inspur.edp.lcm.metadata.inner.api.data.MavenServer;
import com.inspur.edp.lcm.metadata.inner.api.data.PublishStatus;
import com.inspur.edp.lcm.metadata.inner.api.enm.StageEnum;
import com.inspur.edp.lcm.metadata.inner.api.utils.IdeLogUtils;
import com.inspur.edp.lcm.metadata.inner.api.utils.IdeSettingUtils;
import com.inspur.edp.metadata.service.dev.core.threadpool.GspMetadataThreadPoolFactory;
import io.iec.edp.caf.boot.context.CAFContext;
import io.iec.edp.caf.commons.utils.SpringBeanUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.maven.model.Dependency;
import org.apache.maven.model.DeploymentRepository;
import org.apache.maven.model.DistributionManagement;
import org.apache.maven.model.Model;
import org.apache.maven.model.Parent;
import org.apache.maven.model.io.xpp3.MavenXpp3Reader;
import org.apache.maven.model.io.xpp3.MavenXpp3Writer;
import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipInputStream;

/**
 * @author zhaoleitr
 */
@Slf4j
public class PackageCoreService {

    private final FileServiceImp fileServiceImp = new FileServiceImp();
    private final MavenInvoker mavenInvoker = new MavenInvoker();
    private final MetadataProjectCoreService metadataProjectCoreService = new MetadataProjectCoreService();

    private String downloadPath;
    private MetadataProject metadataProject;
    private final Lock lock = new ReentrantLock();
    private static final RestTemplate restTemplate = new RestTemplate();
    private ApiModuleInfo apiModuleInfo = null;
    private List<String> downloadMdpkgPaths;
    private final List<MavenMirror> publicMirrors = new ArrayList<>();
    private final String alimavenFlag = "maven.aliyun.com";

    public PackageCoreService() {
        String path = System.getenv("Path");
        if (path != null) {
            String[] allPath = path.split(";");
            for (String s : allPath) {
                if (s.contains("maven")) {
                    s = s.substring(0, s.length() - 4);
                    System.setProperty("MAVEN_HOME", s);
                }
            }
        }

        MavenMirror gspMirror = new MavenMirror("gsp-releases-repo", "gsp-releases", "https://repos.iec.io/repository/maven-gsp-releases/", "gsp-rep");
        MavenMirror bfMirror = new MavenMirror("bf-releases-repo", "bf-releases", "https://repos.iec.io/repository/maven-bf-releases/", "bf-rep");
        publicMirrors.add(gspMirror);
        publicMirrors.add(bfMirror);

    }

    public void compile(String absolutePath, String modules, String mavenPath) {
        String javaProjPath = fileServiceImp.getCombinePath(absolutePath, "java" + File.separator + "code");
        if (!new File(javaProjPath, Utils.getPomFile()).exists()) {
            return;
        }

        MetadataCompilerContext metadataCompilerContext = new MetadataCompilerContext(absolutePath);
        // 编译前检查代码是否含有代码，以及代码是否变更
        MavenBeforeCompileActionImpl.getInstance().validate(metadataCompilerContext);
        boolean sourceFileChanged = MavenBeforeCompileActionImpl.getInstance().isSourceFileChanged(metadataCompilerContext);
        if (!sourceFileChanged) {
            return;
        }

        mavenInvoker.execute(javaProjPath, handleCompileGoal(modules), mavenPath);

        // 编译后更新代码变更记录
        MavenAfterCompileActionImpl.getInstance().updateSourceFileChanges(new MetadataCompilerContext(absolutePath));
    }

    public void batchOperation(String absolutePath, String mavenPath, List<String> operations) {
        List<String> projPaths = new ArrayList<>();
        metadataProjectCoreService.getProjPathsInPath(absolutePath, projPaths);
        batchOperation(projPaths, mavenPath, operations);
    }

    public void batchOperation(List<String> projPaths, String mavenPath, List<String> operations) {
        Map<String, MdprojInfoDto> mdprojInfoDtos = metadataProjectCoreService.transformToMdprojInfoDto(projPaths);
        Map<String, MdprojInfoDto> path2MdProjInfoDtoMaps = new HashMap<>();
        for(MdprojInfoDto mdprojInfoDto : mdprojInfoDtos.values()){
            path2MdProjInfoDtoMaps.put(mdprojInfoDto.getProjPath(),mdprojInfoDto);
        }
        List<String> buildOrder = metadataProjectCoreService.getBuildOrder(mdprojInfoDtos);
        GenerateService generateService = SpringBeanUtils.getBean(GenerateService.class);
        List<String> errorMsgs = new ArrayList<>();
        IdeLogService ideLogService = IdeLogUtils.getIdeLogService();
        int count = 0;
        for (String projPath : buildOrder) {
            try {
                count ++;
                String start = LcmMetadataDevLog.getInstance().getString(LogCodes.LOG_METADATA_DEV_0004, projPath);
                if(Objects.nonNull(ideLogService)){
                    ideLogService.pushLog("[INFO]" + start, CAFContext.current.getUserId());
                }
                // 仅生成型参与生成代码
                if (operations.contains("generate") &&
                    !ProcessMode.interpretation.equals(path2MdProjInfoDtoMaps.get(projPath).getMetadataProject().getMetadataPackageInfo().getProcessMode())) {
                    generateService.generate(projPath);
                }
                IdeLogUtils.syncProcess(
                    PublishStatus.success(IdeLogUtils.calcProcess(buildOrder.size(),count, StageEnum.GENERATE), StageEnum.GENERATE.getCode())
                );
                // 发布流程中使用，为了使进度条跳跃更加平缓
                Thread.sleep(Utils.PUBLISH_WAIT_TIME);
                String end = LcmMetadataDevLog.getInstance().getString(LogCodes.LOG_METADATA_DEV_0005, projPath);
                if(Objects.nonNull(ideLogService)){
                    ideLogService.pushLog("[INFO]" + end, CAFContext.current.getUserId());
                }
            } catch (Exception e) {
                IdeLogUtils.setStageStatus(IdeLogUtils.Fail);
                IdeLogUtils.syncProcess(PublishStatus.fail(LcmMetadataDevLog.getInstance().getString(LogCodes.LOG_METADATA_DEV_0006, projPath, e.getMessage())));
                String excep = LcmMetadataDevLog.getInstance().getString(LogCodes.LOG_METADATA_DEV_0007, projPath);
                if(Objects.nonNull(ideLogService)){
                    Writer errMsg = new StringWriter();
                    e.printStackTrace(new PrintWriter(errMsg));
                    ideLogService.pushLog("[ERROR] >>> " + errMsg.toString(), CAFContext.current.getUserId());
                    ideLogService.pushLog("[ERROR]" + excep, CAFContext.current.getUserId());
                }
                errorMsgs.add(projPath + ":" + e.getMessage());
            }
            // 如果有工程执行报错，则终止发布流程
            if(!IdeLogUtils.SUCCESS.equals(IdeLogUtils.getStageStatus())){
                return ;
            }
        }
        count = 0;
        for (String projPath : buildOrder) {
            try {
                count ++;
                String start = LcmMetadataDevLog.getInstance().getString(LogCodes.LOG_METADATA_DEV_0004, projPath);
                if(Objects.nonNull(ideLogService)){
                    ideLogService.pushLog("[INFO]" + start, CAFContext.current.getUserId());
                }
                // 上一个工程执行进度
                int lastProcess = IdeLogUtils.calcProcess(buildOrder.size(), count-1, StageEnum.MAVEN_COMPILE);
                // 当前工程执行进度
                int currentProcess = IdeLogUtils.calcProcess(buildOrder.size(),count,StageEnum.MAVEN_COMPILE);
                if (operations.contains("compile")) {
                    if(ProcessMode.generation.equals(path2MdProjInfoDtoMaps.get(projPath).getMetadataProject().getMetadataPackageInfo().getProcessMode())){
                        IdeLogUtils.setGenerationThreadLocal(true);
                        IdeLogUtils.setMinProcess(lastProcess);
                        IdeLogUtils.setMaxProcess(currentProcess);
                        compile(projPath, "api,core,comp", mavenPath);
                    }else{
                        // 检测到有pom才执行编译
                        if(new File(fileServiceImp.getCombinePath(projPath, "java" + File.separator + "code" + File.separator + "pom.xml")).exists()){
                            IdeLogUtils.setGenerationThreadLocal(false);
                            IdeLogUtils.setMinProcess(lastProcess);
                            IdeLogUtils.setMaxProcess(currentProcess);
                            compile(projPath, "all", mavenPath);
                        }
                    }
                }
                IdeLogUtils.syncProcess(
                    PublishStatus.success(currentProcess,StageEnum.MAVEN_COMPILE.getCode())
                );
                Thread.sleep(Utils.PUBLISH_WAIT_TIME);
                String end = LcmMetadataDevLog.getInstance().getString(LogCodes.LOG_METADATA_DEV_0005, projPath);
                if(Objects.nonNull(ideLogService)){
                    ideLogService.pushLog("[INFO]" + end, CAFContext.current.getUserId());
                }
            } catch (Exception e) {
                IdeLogUtils.setStageStatus(IdeLogUtils.Fail);
                IdeLogUtils.syncProcess(PublishStatus.fail(LcmMetadataDevLog.getInstance().getString(LogCodes.LOG_METADATA_DEV_0008, projPath, e.getMessage())));
                String excep = LcmMetadataDevLog.getInstance().getString(LogCodes.LOG_METADATA_DEV_0007, projPath);
                if(Objects.nonNull(ideLogService)){
                    Writer errMsg = new StringWriter();
                    e.printStackTrace(new PrintWriter(errMsg));
                    ideLogService.pushLog("[ERROR] >>> " + errMsg.toString(), CAFContext.current.getUserId());
                    ideLogService.pushLog("[ERROR]" + excep, CAFContext.current.getUserId());
                }
                errorMsgs.add(projPath + ":" + e.getMessage());
            } finally {
                IdeLogUtils.removeGenerationThreadLocal();
                IdeLogUtils.removeMinProcess();
                IdeLogUtils.removeMaxProcess();
            }
            if(!IdeLogUtils.SUCCESS.equals(IdeLogUtils.getStageStatus())){
                return ;
            }
        }
        try {
            // 防止其他的日志输出比这个晚。
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            IdeLogUtils.setStageStatus(IdeLogUtils.Fail);
        }
        if (!errorMsgs.isEmpty()) {
            String log = (LcmMetadataDevLog.getInstance().getString(LogCodes.LOG_METADATA_DEV_0009));
            if(Objects.nonNull(ideLogService)){
                ideLogService.pushLog(log, CAFContext.current.getUserId());
            }
            for (String msg : errorMsgs) {
                if(Objects.nonNull(ideLogService)){
                    ideLogService.pushLog("[ERROR]" + msg, CAFContext.current.getUserId());
                }
            }
        } else {
            if(Objects.nonNull(ideLogService)){
                ideLogService.pushLog(LcmMetadataDevLog.getInstance().getString(LogCodes.LOG_METADATA_DEV_0010), CAFContext.current.getUserId());
            }
        }
    }

    public void restore(String absolutePath, Boolean force, String mavenPath, String packagePath) {
        if (Utils.isNullOrEmpty(absolutePath)) {
            throw new IllegalArgumentException("工程路径不能为空");
        }
        MetadataProjectCoreService projectCoreService = new MetadataProjectCoreService();
        absolutePath = projectCoreService.getProjPath(absolutePath);
        MetadataProject metadataProjInfo = projectCoreService.getMetadataProjInfo(absolutePath);
        Utils.checkNPE(metadataProjInfo, "获取元数据工程信息失败，工程路径为：" + absolutePath);

        List<MavenPackageRefs> mavenPackageRefsList = metadataProjInfo.getMavenPackageRefs();
        if (Utils.isNullOrEmpty(mavenPackageRefsList)) {
            return;
        }

        // bo间工程引用
        List<ProjectHeader> projectHeaderList = metadataProjInfo.getProjectRefs();
        removeProjectRefs(absolutePath, mavenPackageRefsList, projectHeaderList);

        boolean installFlag;
        List<MavenPackageRefs> needInstallPackages = new ArrayList<>();
        for (MavenPackageRefs ref : mavenPackageRefsList) {
            installFlag = getInstallFlag(ref, force, mavenPath, packagePath);
            if (installFlag) {
                needInstallPackages.add(ref);
            }
        }
        try {
            log.info("元数据开始下载");
            doRestore(needInstallPackages, absolutePath, force, mavenPath, packagePath);
        } catch (IOException e) {
            throw new LcmMavenDevException(e, ErrorCodes.ECP_MAVEN_DEV_0005, absolutePath);
        }
    }

    public void addDependencyAndRestore(String absolutePath, List<String> metadataPackages) {
        String projPath = metadataProjectCoreService.getProjPath(absolutePath);
        MetadataProject metadataProject = metadataProjectCoreService.getMetadataProjInfo(projPath);
        metadataPackages.forEach(item -> {
            MetadataPackageHeader packageHeader = handleMetadataPackageName(item);
            // 更新依赖
            metadataProjectCoreService.updateDbRefs(projPath, metadataProject, packageHeader);
        });
    }

    public void doRestore(List<MavenPackageRefs> refs, String absolutePath, boolean forceUpdateFlag, String mavenPath, String packagePath) throws IOException {
        // 防止工作空间未初始化maven文件夹
        if (!fileServiceImp.isDirectoryExist(mavenPath)) {
            fileServiceImp.createDirectory(mavenPath);
        }

        String metadataPath = fileServiceImp.getCombinePath(absolutePath, Utils.getMetadataProjPath());
        String pomPath = fileServiceImp.getCombinePath(metadataPath, MavenUtils.pomFile);
        ProcessMode processMode = metadataProjectCoreService.getProcessMode(absolutePath);
        try {
            // 创建pom
            final PomManager pomManager = new PomManager();
            pomManager.createPomForDependencyCopy(refs, pomPath);

            // copy dependency
            downloadPath = fileServiceImp.getCombinePath(mavenPath, MavenUtils.tempFolder);
            copyDependencies(metadataPath, mavenPath, downloadPath, forceUpdateFlag);

            // 解压并复制下载的元数据包到maven目录下
            extractMd(downloadPath, mavenPath);

            if (downloadMdpkgPaths != null && downloadMdpkgPaths.size() > 0) {
                CopyToPackagesRunnable copyToPackagesRunnable = new CopyToPackagesRunnable();
                copyToPackagesRunnable.setDownloadMdpkgPaths(downloadMdpkgPaths);
                copyToPackagesRunnable.setPackagePath(packagePath);
                GspMetadataThreadPoolFactory.getRestoreExecutorService().submit(copyToPackagesRunnable);
            }

            // 下载jar
            if (forceUpdateFlag && ProcessMode.generation.equals(processMode)) {
                InstallJarRunnable installJarRunnable = new InstallJarRunnable();
                installJarRunnable.setPomPath(pomPath);
                installJarRunnable.setDownloadMdpkgPaths(downloadMdpkgPaths);
                installJarRunnable.setPomDirPath(metadataPath);
                installJarRunnable.setForceUpdateFlag(true);
                installJarRunnable.setMavenPath(mavenPath);
                installJarRunnable.setDownloadPath(downloadPath);
                GspMetadataThreadPoolFactory.getRestoreExecutorService().submit(installJarRunnable);
            }
        } finally {
            if (!forceUpdateFlag || !ProcessMode.generation.equals(processMode)) {
                //删除pom.xml
                if (fileServiceImp.isFileExist(pomPath)) {
                    fileServiceImp.fileDelete(pomPath);
                }
                //删除\projects\maven/temp
                if (fileServiceImp.isDirectoryExist(downloadPath)) {
                    fileServiceImp.deleteAllFilesUnderDirectory(downloadPath);
                }
            }
        }
    }

    public void installMdpkg(String groupId, String artifactId, String version, String absolutePath,
                             Boolean forceUpdateFlag, String mavenPath, String packagePath,
                             String metadataPackageName) throws IOException {
        //创建pom文件,对应的mdproj添加依赖信息
        absolutePath = metadataProjectCoreService.getProjPath(absolutePath);
        String metadataPath = absolutePath + File.separator + "metadata";
        String desPath = new File(mavenPath).getAbsolutePath();
        if (!fileServiceImp.isDirectoryExist(desPath)) {
            fileServiceImp.createDirectory(desPath);
        }
        try {
            boolean isDone = createPomAndDownloadMdproj(groupId, artifactId, version, metadataPath, forceUpdateFlag, mavenPath);
            if (!isDone) {
                throw new LcmMavenDevException(ErrorCodes.ECP_MAVEN_DEV_0004, groupId, artifactId, version);
            }
            if (!addDependencyToMdproj(groupId, artifactId, version, metadataPath, metadataPackageName)) {
                throw new LcmMetadataDevException(ErrorCodes.ECP_METADATA_DEV_0025, groupId, artifactId, version, metadataPath);
            }

            //解压并复制下载的元数据包到/projects/maven目录下，结构和nuget对齐。
            extractMd(downloadPath, mavenPath);

            if (downloadMdpkgPaths != null && downloadMdpkgPaths.size() > 0) {
                CopyToPackagesRunnable copyToPackagesRunnable = new CopyToPackagesRunnable();
                copyToPackagesRunnable.setDownloadMdpkgPaths(downloadMdpkgPaths);
                copyToPackagesRunnable.setPackagePath(packagePath);
                GspMetadataThreadPoolFactory.getInstallMdpkgExecutorService().submit(copyToPackagesRunnable);
            }

            //下载jar包
            ProcessMode processMode = metadataProjectCoreService.getProcessMode(absolutePath);
            if (version.contains("SNAPSHOT") && forceUpdateFlag && ProcessMode.generation.equals(processMode)) {
                InstallSingleJarRunnable installSingleJarRunnable = new InstallSingleJarRunnable();
                installSingleJarRunnable.setPomDirPath(metadataPath);
                installSingleJarRunnable.setDownloadPath(downloadPath);
                installSingleJarRunnable.setMavenPath(mavenPath);
                GspMetadataThreadPoolFactory.getInstallMdpkgExecutorService().submit(installSingleJarRunnable);
            }
        } finally {
            String metadataPomPath = fileServiceImp.getCombinePath(metadataPath, MavenUtils.pomFile);
            //删除pom.xml
            if (fileServiceImp.isFileExist(metadataPomPath)) {
                fileServiceImp.fileDelete(metadataPomPath);
            }
            //删除\projects\maven/temp
            if (!version.contains("SNAPSHOT") || !forceUpdateFlag) {
                if (fileServiceImp.isDirectoryExist(downloadPath)) {
                    fileServiceImp.deleteAllFilesUnderDirectory(downloadPath);
                }
            }
        }
    }

    public void uninstallMdpkg(String absolutePath, String packName, String mavenPath) {
        int divideIndex = packName.indexOf("-");
        String groupId = packName.substring(0, divideIndex);
        String artifactId = packName.substring(divideIndex + 1);
        MavenPackageRefs mavenPackageRefs = new MavenPackageRefs();
        mavenPackageRefs.setGroupId(groupId);
        mavenPackageRefs.setArtifactId(artifactId);

        MetadataProject metadataProject = metadataProjectCoreService.getMetadataProjInfo(absolutePath);
        RepositoryFactory.getInstance().getMetadataProjectRepository().removeMavenRefs(absolutePath, metadataProject, mavenPackageRefs);

        PackageNameManager packageNameManager = new PackageNameManager();
        String mdpkgName = packageNameManager.getMdpkgNameByGA(groupId, artifactId, mavenPath, absolutePath);
        if (mdpkgName.isEmpty()) {
            throw new LcmMetadataDevException(ErrorCodes.ECP_METADATA_DEV_0026, packName);
        }

        List<String> mdpkgNames = new ArrayList<>();
        mdpkgNames.add(mdpkgName);
        RepositoryFactory.getInstance().getMetadataProjectRepository().removeProjectRefs(absolutePath, metadataProject, mdpkgNames);

        MetadataPackageHeader metadataPackageHeader = new MetadataPackageHeader();
        metadataPackageHeader.setName(mdpkgName);
        RepositoryFactory.getInstance().getMetadataProjectRepository().removeRefs(absolutePath, metadataProject, metadataPackageHeader);
    }

    public void addProjectDependency(String pomPath, String groupId, String artifactId, String version) {
        try (FileInputStream fis = new FileInputStream(pomPath)) {
            MavenXpp3Reader reader = new MavenXpp3Reader();
            Model model = reader.read(fis);
            List<Dependency> list = model.getDependencies();
            Dependency dependency = new Dependency();
            dependency.setGroupId(groupId);
            dependency.setArtifactId(artifactId);
            if (version.startsWith("m")) {
                dependency.setVersion(version.substring(1));
            } else {
                dependency.setVersion(version);
            }
            //需要判断依赖信息。依赖信息中不允许有重复。
            boolean isDependencyExits = false;
            for (Dependency dep : list) {
                if (dep.getGroupId().equals(groupId) && dep.getArtifactId().equals(artifactId)) {
                    //如果groupId，artifactId相同，则更新版本号。
                    isDependencyExits = true;
                    if (version.startsWith("m")) {
                        dep.setVersion(version.substring(1));
                    } else {
                        dep.setVersion(version);
                    }
                }
            }
            if (!isDependencyExits) {
                list.add(dependency);
            }
            model.setDependencies(list);
            MavenXpp3Writer mavenXpp3Writer = new MavenXpp3Writer();
            try (FileOutputStream fileOutputStream = new FileOutputStream(pomPath)) {
                mavenXpp3Writer.write(fileOutputStream, model);
            }
        } catch (IOException | XmlPullParserException e) {
            log.error("[{}]增加工程依赖[{}:{}:{}]失败",pomPath, groupId, artifactId, version, e);
        }
    }

    public void deployReleaseMdVersion(String projPath, String version, String repoId, boolean revert, String dependenciesVersion, String mavenPath) throws IOException {
        if (projPath == null || projPath.isEmpty()) {
            throw new IllegalArgumentException("工程路径不能为空");
        }
        if (version == null || version.isEmpty()) {
            throw new IllegalArgumentException("version不能为空");
        }
        String codepath = projPath + File.separator + "java" + File.separator + Utils.getMavenProName();

        String apiPomPath = fileServiceImp.getApiModulePath(projPath) + File.separator + MavenUtils.pomFile;
        String revertCommand = "versions:revert";
        String commitCommand = "versions:commit";
        String command = String.format("versions:set -DnewVersion=%s", version);
        //更新release版本号
        mavenInvoker.execute(codepath, command, mavenPath);
        //根据前端dependencies进行版本号变更
        if (!StringUtils.isEmpty(dependenciesVersion)) {
            List<Dependency> list = null;
            Model model = null;
            try (FileInputStream fis = new FileInputStream(apiPomPath)) {
                MavenXpp3Reader reader = new MavenXpp3Reader();
                model = reader.read(fis);
                list = model.getDependencies();
                for (Dependency dependency : list) {
                    if (dependency.getVersion() != null) {
                        if (dependency.getVersion().endsWith(MavenUtils.snapShot)) {
                            dependency.setVersion(dependenciesVersion);
                        }
                    }
                }

            } catch (IOException | XmlPullParserException e) {
                log.error("更新[{}]工程依赖版本为[{}]失败", projPath, dependenciesVersion, e);
            }
            if (model != null) {
                model.setDependencies(list);
            } else {
                throw new LcmMavenDevException(ErrorCodes.ECP_MAVEN_DEV_0006, codepath);
            }
            FileOutputStream fos = new FileOutputStream(apiPomPath);
            MavenXpp3Writer mavenXpp3Writer = new MavenXpp3Writer();
            mavenXpp3Writer.write(fos, model);
            fos.close();
        }
        //然后进行推送操作
        try {
            deployMdpkg(projPath, repoId, dependenciesVersion, mavenPath);
        } finally {
            if (revert) {
                mavenInvoker.execute(codepath, revertCommand, mavenPath);
            } else {
                mavenInvoker.execute(codepath, commitCommand, mavenPath);
            }
        }
    }

    public void deploySnapshotMdVersion(String projPath, String repoId, String version, boolean revert, String mavenPath) {
        if (projPath == null || projPath.isEmpty()) {
            throw new IllegalArgumentException("工程路径不能为空");
        }
        if (version == null || version.isEmpty()) {
            throw new IllegalArgumentException("version不能为空");
        }

        String codePath = projPath + File.separator + "java" + File.separator + Utils.getMavenProName();
        String revertCommand = "versions:revert";
        String commitCommand = "versions:commit";
        String command = String.format("versions:set -DnewVersion=%s", version);
        //更新版本号
        mavenInvoker.execute(codePath, command, mavenPath);
        //然后进行推送操作
        try {
            deployMdpkg(projPath, repoId, null, mavenPath);
        } finally {
            if (revert) {
                mavenInvoker.execute(codePath, revertCommand, mavenPath);
            } else {
                mavenInvoker.execute(codePath, commitCommand, mavenPath);
            }
        }
    }

    public void deployMdpkgForInterpretation(String projPath, String repoId, String version, String dependencyVersion, String mavenPath) {
        final MavenDeploymentForMdpkgManager mavenDeploymentForMdpkgManager = new MavenDeploymentForMdpkgManager();
        mavenDeploymentForMdpkgManager.deploy(projPath, repoId, version, dependencyVersion, mavenPath);
    }

    public void deployMdpkg(String proPath, String repoId, String dependencyVersion, String mavenPath) {
        String repoUrl = getRepoUrl(repoId);
        if (repoUrl == null || repoUrl.isEmpty()) {
            throw new IllegalArgumentException("获取repoUrl失败，请检查" + mavenPath + "/config/settings.xml配置");
        }
        boolean isModelExist = isJavaProjExist(proPath);
        //接下来拷贝元数据
        String moduleApiPath;
        String codePath = proPath + File.separator + "java" + File.separator + Utils.getMavenProName();
        String codePom = fileServiceImp.getCombinePath(codePath, MavenUtils.pomFile);
        String apiPomPath;
        String metadataBin = File.separator + "metadata" + File.separator + "bin";
        String metadataBinPath = proPath + metadataBin;
        String metadataPath = File.separator + "metadata";
        String metadataDir = proPath + metadataPath;
        String metadataTempDir = fileServiceImp.getCombinePath(metadataDir, MavenUtils.tempFolder);
        if (isModelExist) {
            moduleApiPath = fileServiceImp.getApiModulePath(proPath);
            apiPomPath = fileServiceImp.getCombinePath(moduleApiPath, MavenUtils.pomFile);
            //读mdproj获取依赖信息
            metadataProject = metadataProjectCoreService.getMetadataProjInfo(metadataDir);
            List<MavenPackageRefs> refsList = metadataProject.getMavenPackageRefs();
            try {
                //获取api module的groupId,artifactId,version
                apiModuleInfo = getApiModuleInfo(apiPomPath);
                if (apiModuleInfo != null) {
                    boolean isSnapshot = apiModuleInfo.getVersion().endsWith(MavenUtils.snapShot);
                    setRepoUrl(codePom, repoUrl, repoId, isSnapshot);
                }
                createPomForDeploy(apiModuleInfo, refsList, metadataTempDir, repoUrl, repoId, dependencyVersion);
                boolean isCreated = createSrcDir(metadataTempDir);
                if (!isCreated) {
                    log.error("创建资源目录失败");
                }
            } catch (IOException e) {
                log.error("创建资源目录失败", e);
            }
            //获取工程下元数据包名
            String metadaPackageName = "";
            List<File> list = fileServiceImp.getAllFiles(metadataBinPath);
            for (File file : list) {
                if (file.getName().endsWith(Utils.getMetadataPackageExtension())) {
                    metadaPackageName = file.getName();
                }
            }
            if (metadaPackageName.isEmpty()) {
                throw new LcmMetadataDevException(ErrorCodes.ECP_METADATA_DEV_0023, proPath);
            }
            String metadataFullPath = metadataBinPath + File.separator + metadaPackageName;
            String destPath = metadataTempDir + File.separator + MavenUtils.resourcesDir + File.separator + metadaPackageName;
            try {
                fileServiceImp.fileCopy(metadataFullPath, destPath);
            } catch (IOException e) {
                log.error("file copy failed", metadataFullPath, destPath);
            }
            try {
                mavenInvoker.execute(metadataTempDir, "deploy", mavenPath);
            } finally {
                try {
                    fileServiceImp.deleteAllFilesUnderDirectory(metadataTempDir);
                } catch (IOException e) {
                    log.error("delete file failed", metadataTempDir);
                }
            }

            mavenInvoker.execute(codePath, "deploy -pl api -am", mavenPath);
            try {
                String processMode = metadataProject.getMetadataPackageInfo().getProcessMode() == null ? "generation" : metadataProject.getMetadataPackageInfo().getProcessMode().toString();
                updateMetadataIndexWithProcessMode(metadaPackageName, metadataBinPath, repoUrl, apiModuleInfo, processMode);
            } catch (Exception e) {
                updateMetadataIndex(metadaPackageName, metadataBinPath, repoUrl, apiModuleInfo);
            }
        } else {
            throw new LcmMetadataDevException(ErrorCodes.ECP_METADATA_DEV_0027, proPath);
        }
    }

    public List<MavenPackageRefWithProcessMode> getPackageRefs(String absolutePath, String mavenPath) {
        MetadataProject metadataProjInfo = metadataProjectCoreService.getMetadataProjInfo(absolutePath);
        if (metadataProjInfo == null) {
            throw new LcmMetadataDevException(ErrorCodes.ECP_METADATA_DEV_0004, absolutePath);
        }
        if (CollectionUtils.isEmpty(metadataProjInfo.getMavenPackageRefs())) {
            return new ArrayList<>();
        }

        List<MavenPackageRefWithProcessMode> refs = new ArrayList<>();
        PackageNameManager packageNameManager = new PackageNameManager();
        metadataProjInfo.getMavenPackageRefs().forEach(mavenPackageRefs -> {
            MavenPackageRefWithProcessMode mavenPackageRefWithProcessMode = new MavenPackageRefWithProcessMode(mavenPackageRefs.getGroupId(), mavenPackageRefs.getArtifactId(), mavenPackageRefs.getVersion());
            String mdpkgName = packageNameManager.getMdpkgNameByGA(mavenPackageRefs.getGroupId(), mavenPackageRefs.getArtifactId(), mavenPath, metadataProjInfo);
            if (StringUtils.isEmpty(mdpkgName)) {
                log.info("无法根据" + mavenPackageRefs.getGroupId() + "-" + mavenPackageRefs.getArtifactId() + "获取准确的元数据包名");
                mavenPackageRefWithProcessMode.setProcessMode(ProcessMode.generation);
                refs.add(mavenPackageRefWithProcessMode);
                return;
            }
            if (!CollectionUtils.isEmpty(metadataProjInfo.getMetadataPackageRefs())) {
                MetadataPackageHeader packageHeader = metadataProjInfo.getMetadataPackageRefs().stream().filter(metadataPackageHeader -> metadataPackageHeader.getName().equalsIgnoreCase(mdpkgName)).findFirst().orElse(null);
                if (packageHeader == null) {
                    log.info("无法根据元数据包名[{}] 获取对应的元数据工程引用", mdpkgName);
                    mavenPackageRefWithProcessMode.setProcessMode(ProcessMode.generation);
                } else {
                    mavenPackageRefWithProcessMode.setProcessMode(packageHeader.getProcessMode());
                }
                refs.add(mavenPackageRefWithProcessMode);
            }
        });

        return refs;
    }

    public MavenComponents getVersionsOfSinglePackage(String sourceUrl, String packName) {
        String[] urlSections = sourceUrl.split("/");
        String repository = urlSections[urlSections.length - 1];
        String groupId = packName.substring(0, packName.indexOf("-"));
        String artifactId = packName.substring(packName.indexOf("-") + 1);
        String url = "https://repos.iec.io/service/rest/v1/search?repository=" +
                repository +
                "&group=" +
                groupId +
                "&name=" +
                artifactId +
                "&sort=version";
        try {
            HttpHeaders headers = new HttpHeaders();
            headers.setBasicAuth("igix-web-ide", "imUIz2J#mEgmkvRS");
            HttpEntity<Object> entity = new HttpEntity<>(null, headers);
            ResponseEntity<MavenComponents> response = restTemplate.exchange(url, HttpMethod.GET, entity, MavenComponents.class);
            return response.getBody();
        } catch (Exception e) {
            return null;
        }
    }

    public String getMavenPackageLatestVersion(String groupId, String artifactId) {
        // 首先从gsp-releases获取，如果可以连接外网，则可以获取。
        String version = getMavenPackageVersionsFromGsp(groupId, artifactId);
        if ("0.1.0".equals(version)) {
            // 读取settings.xml中的仓库，循环查找版本
            try {
                version = getMavenPackageVersionsFromRepository(groupId, artifactId);
            } catch (MalformedURLException e) {
            }
        }
        return version;
    }

    private String getMavenPackageVersionsFromGsp(String groupId, String artifactId) {
        String version = "0.1.0";
        try {
            String url = "https://repos.iec.io/service/rest/v1/search?repository=maven-gsp-releases&group=" + groupId + "&name=" + artifactId + "&sort=version";
            HttpHeaders headers = new HttpHeaders();
            headers.setBasicAuth("igix-web-ide", "imUIz2J#mEgmkvRS");
            HttpEntity<Object> entity = new HttpEntity<>(null, headers);
            ResponseEntity<MavenComponents> response = restTemplate.exchange(url, HttpMethod.GET, entity, MavenComponents.class);
            MavenComponents body = response.getBody();
            if (body != null) {
                // 如果查找到版本，排序获取最新版本
                for (MavenComponent item : body.getItems()) {
                    version = VersionManager.versionCompare(version, item.getVersion().replace("m", ""));
                }
            }
        } catch (Exception e) {
        }
        return version;
    }

    private String getMavenPackageVersionsFromRepository(String groupId, String artifactId) throws MalformedURLException {
        String version = "0.1.0";
        IdeSettingService ideSettingService = IdeSettingUtils.getIdeSettingService();
        if (ideSettingService == null) {
            return version;
        }

        for (MavenMirror mirror : ideSettingService.getMirrors()) {
            if (mirror.getUrl() == null || mirror.getId() == null) {
                break;
            }

            HttpHeaders headers = null;
            for (MavenServer server : ideSettingService.getServers()) {
                if (server.getId().equals(mirror.getId())) {
                    headers = new HttpHeaders();
                    headers.setBasicAuth(server.getUsername(), server.getPassword());
                    break;
                }
            }
            if (headers == null) {
                break;
            }

            final URL url = new URL(mirror.getUrl());
            final String[] splitUrl = mirror.getUrl().split("/");
            String repository = splitUrl[splitUrl.length - 1];
            String searchUrl = url.getProtocol() + "://" + url.getHost();
            searchUrl += url.getPort() == -1 ? "" : ":" + url.getPort();
            searchUrl += "/service/rest/v1/search?repository=" + repository + "&group=" + groupId + "&name=" + artifactId + "&sort=version";

            try {
                HttpEntity<Object> entity = new HttpEntity<>(null, headers);
                ResponseEntity<MavenComponents> response = restTemplate.exchange(searchUrl, HttpMethod.GET, entity, MavenComponents.class);
                // 如果查找到版本，排序获取最新版本
                if (response.getBody() != null && response.getBody().getItems() != null && response.getBody().getItems().size() > 0) {
                    for (MavenComponent item : response.getBody().getItems()) {
                        version = versionCompareRelease(version, item.getVersion().replace("m", ""));
                    }
                }
            } catch (Exception e) {
            }
        }
        return version;
    }

    private String versionCompareRelease(String existVersion, String newVersion) {
        if (newVersion.contains("-")) {
            return existVersion;
        } else {
            return VersionManager.versionCompare(existVersion, newVersion);
        }
    }

    public MetadataRepo getRepoList() {
        IdeSettingService ideSettingService = IdeSettingUtils.getIdeSettingService();
        if(Objects.isNull(ideSettingService)){
            return null;
        }
        List<MavenMirror> mirrors = ideSettingService.getMirrors();
        if(CollectionUtils.isEmpty(mirrors)){
            return null;
        }
        return transferMirrorsToMetadataRepo(mirrors);
    }

    public MetadataRepo getHostedRepoList() {
        final List<MavenMirror> mirrors = getHostedMirrors();
        return transferMirrorsToMetadataRepo(mirrors);
    }

    private List<MavenMirror> getHostedMirrors() {
        List<MavenMirror> mirrorsList = new ArrayList<>();

        IdeSettingService ideSettingService = IdeSettingUtils.getIdeSettingService();
        if(Objects.nonNull(ideSettingService)){
            List<MavenMirror> result = ideSettingService.getMirrors();
            if(!CollectionUtils.isEmpty(result)){
                mirrorsList.addAll(result);
            }
        }
        // 去掉aliyun
        List<MavenMirror> mirrors = mirrorsList.stream().filter(mirror -> !mirror.getUrl().contains(alimavenFlag)).collect(Collectors.toList());
        // 加上gsp和bf
        publicMirrors.forEach(publicMirror -> {
            if (mirrors.stream().noneMatch(mirror -> mirror.getUrl().equals(publicMirror.getUrl()))) {
                mirrors.add(publicMirror);
            }
        });
        return mirrors;
    }

    private MetadataRepo transferMirrorsToMetadataRepo(List<MavenMirror> mirrors) {
        MetadataRepo metadataRepo = new MetadataRepo();
        List<PackageSourceDto> sourceDtos = new ArrayList<>();
        mirrors.forEach(mirror -> {
            final PackageSourceDto packageSourceDto = new PackageSourceDto();
            packageSourceDto.setId(mirror.getId());
            packageSourceDto.setName(mirror.getName());
            packageSourceDto.setSourceUrl(mirror.getUrl());
            sourceDtos.add(packageSourceDto);
        });
        metadataRepo.setRepoList(sourceDtos);
        return metadataRepo;
    }

    private String handleCompileGoal(String modules) {
        StringBuilder sb;
        if ("all".equals(modules)) {
            sb = new StringBuilder("clean install").append(" -T 100C -Dmaven.test.skip=true");
        } else {
            sb = new StringBuilder("clean install -pl ").append(modules).append(" -T 100C -Dmaven.test.skip=true");
        }

        if (modules.contains("api")) {
            sb.append(" -am ");
        }
        return sb.toString();
    }

    public boolean getInstallFlag(MavenPackageRefs ref, Boolean force, String mavenPath, String packagePath) {
        boolean flagValidMavenRef = ref.getGroupId() != null && ref.getArtifactId() != null && ref.getVersion() != null;
        if (!flagValidMavenRef) {
            String log = "[WARNING]" + "存在不合法的maven引用，GAV：" + ref.getGroupId() + "," + ref.getArtifactId() + "," + ref.getVersion();
            if(Objects.nonNull(IdeLogUtils.getIdeLogService())){
                IdeLogUtils.getIdeLogService().pushLog(log, CAFContext.current.getUserId());
            }
            return false;
        }

        // 是临时包则下载;maven文件夹下需要元数据包和pom文件，缺一则下载;packages文件夹下需要元数据包，缺少则下载
        boolean installFlag = ref.getVersion().contains(MavenUtils.snapShot) && force;
        if (!installFlag) {
            List<File> fileInMaven = fileServiceImp.getAllFiles(mavenPath + File.separator + ref.getGroupId() + "-" + ref.getArtifactId() + "-" + ref.getVersion());
            installFlag = fileInMaven.size() < 2;
            if (!installFlag) {
                File mdpkg = fileInMaven.stream().filter(file -> file.getName().endsWith(".mdpkg")).findAny().orElse(null);
                installFlag = mdpkg == null || !fileServiceImp.isFileExist(packagePath + File.separator + mdpkg.getName() + File.separator + mdpkg.getName());
            }
        }
        return installFlag;
    }

    public void changeRefProcessMode(String absolutePath, String groupId, String artifactId, ProcessMode processMode, String mavenPath) {
        // 找到mdpkgName
        PackageNameManager packageNameManager = new PackageNameManager();
        String mdpkgName = packageNameManager.getMdpkgNameByGA(groupId, artifactId, mavenPath, absolutePath);
        if (StringUtils.isEmpty(mdpkgName)) {
            throw new LcmMetadataDevException(ErrorCodes.ECP_METADATA_DEV_0028, groupId, artifactId);
        }
        changeRefProcessModeWithArtifactInfo(absolutePath, mdpkgName, processMode, groupId, artifactId);
    }

    @Deprecated
    public void changeRefProcessMode(String absolutePath, String mdpkgName, ProcessMode processMode) {
        // 更改mdproj中的信息
        MetadataProject metadataProjInfo = metadataProjectCoreService.getMetadataProjInfo(absolutePath);
        if (metadataProjInfo == null) {
            throw new LcmMetadataDevException(ErrorCodes.ECP_METADATA_DEV_0004, absolutePath);
        }
        if (CollectionUtils.isEmpty(metadataProjInfo.getMetadataPackageRefs())) {
            throw new LcmMetadataDevException(ErrorCodes.ECP_METADATA_DEV_0029, absolutePath);
        }
        MetadataPackageHeader packageHeader = metadataProjInfo.getMetadataPackageRefs().stream().filter(ref -> ref.getName().equalsIgnoreCase(mdpkgName)).findFirst().orElse(null);
        if (packageHeader == null) {
            throw new LcmMetadataDevException(ErrorCodes.ECP_METADATA_DEV_0030, mdpkgName);
        }
        if (processMode.equals(packageHeader.getProcessMode())) {
            throw new LcmMetadataDevException(ErrorCodes.ECP_METADATA_DEV_0031, processMode.getDesc());
        }
        packageHeader.setProcessMode(processMode);
        metadataProjectCoreService.updateMetadataProject(absolutePath, metadataProjInfo);
        // 删除api.pom或者comp.pom中的引用
        PomManager pomManager = new PomManager();
        Dependency dependency = new Dependency();
        MavenPackageRefs mavenPackageRefs = MdpkgUtils.getGAByMdpkgNameWithApi(mdpkgName);
        dependency.setGroupId(mavenPackageRefs.getGroupId());
        dependency.setArtifactId(mavenPackageRefs.getArtifactId());
        pomManager.deleteDependency(absolutePath, PomManager.API, dependency);
        pomManager.deleteDependency(absolutePath, PomManager.COMP, dependency);
    }

    public void changeRefProcessMode(String absolutePath, GspProject gspProject, ProcessMode processMode) {
        // 更改mdproj中的信息
        updateMetadataPackageHeader(absolutePath, gspProject.getMetadataPackageName(), processMode);

        // 删除api.pom或者comp.pom中的引用
        MavenPackageRefs mavenPackageRefs = MdpkgUtils.getGAWithApi(gspProject.getMetadataPackageName(), gspProject.getPackagePrefix());
        deleteDependency(absolutePath, mavenPackageRefs.getGroupId(), mavenPackageRefs.getArtifactId());
    }

    private void removeProjectRefs(String absolutePath, List<MavenPackageRefs> mavenPackageRefsList, List<ProjectHeader> projectHeaderList) {
        if (Utils.isNullOrEmpty(projectHeaderList) || Utils.isNullOrEmpty(mavenPackageRefsList)) {
            return;
        }

        List<MavenPackageRefs> mavenPackageInfoInBo = new ArrayList<>();
        for (ProjectHeader projectHeader : projectHeaderList) {
            String projPath = fileServiceImp.getCombinePath(absolutePath, projectHeader.getProjectPath());
            if (fileServiceImp.isDirectoryExist(projPath)) {
                GspProject getGspProjectInfo = new GspProjectCoreService().getGspProjectInfo(projPath);
                MavenPackageRefs mavenPackageRefs = MdpkgUtils.getGAWithApi(getGspProjectInfo.getMetadataPackageName(), getGspProjectInfo.getPackagePrefix());
                mavenPackageInfoInBo.add(mavenPackageRefs);
            }
        }

        List<MavenPackageRefs> refForExclude = new ArrayList<>();
        if (mavenPackageInfoInBo.size() > 0) {
            for (MavenPackageRefs mavenPackageRefs : mavenPackageRefsList) {
                for (MavenPackageRefs mavenPackageRefsInBo : mavenPackageInfoInBo) {
                    if (mavenPackageRefs.getGroupId().equals(mavenPackageRefsInBo.getGroupId())
                            && mavenPackageRefs.getArtifactId().equals(mavenPackageRefsInBo.getArtifactId())) {
                        refForExclude.add(mavenPackageRefs);
                    }
                }
            }
            for (MavenPackageRefs mavenPackageRefs : refForExclude) {
                mavenPackageRefsList.remove(mavenPackageRefs);
            }
        }
    }

    private void updateMetadataIndex(String mdpkgName, String mdpkgPath, String repoUrl, ApiModuleInfo apiModuleInfo) {
        MetadataPackage metadataPackage = new MetadataCoreManager().getMetadataPackageInfo(mdpkgName, mdpkgPath);
        if (metadataPackage.getMetadataList() != null && metadataPackage.getMetadataList().size() > 0) {
            PackageWithMetadataInfo packageWithMetadataInfo = new PackageWithMetadataInfo();
            packageWithMetadataInfo.setMavenPackageGroupId(apiModuleInfo.getGroupId());
            packageWithMetadataInfo.setMavenPackageArtifactId(apiModuleInfo.getArtifactId());
            packageWithMetadataInfo.setMavenPackageVersion(apiModuleInfo.getVersion());
            packageWithMetadataInfo.setMavenPackageUrl(repoUrl);

            List<MetadataInfoInMaven> metadatas = new ArrayList<>();
            for (GspMetadata metadata : metadataPackage.getMetadataList()) {
                MetadataInfoInMaven tempMetadata = new MetadataInfoInMaven();
                tempMetadata.setMetadataId(metadata.getHeader().getId());
                tempMetadata.setMetadataCode(metadata.getHeader().getCode());
                tempMetadata.setMetadataName(metadata.getHeader().getName());
                tempMetadata.setMetadataNamespace(metadata.getHeader().getNameSpace());
                tempMetadata.setMetadataType(metadata.getHeader().getType());
                tempMetadata.setMetadataIsTranslating(metadata.getHeader().isTranslating() ? "t" : "f");
                tempMetadata.setMdBizobjectId(metadata.getHeader().getBizobjectID());
                tempMetadata.setMetadataPackageCode(metadataPackage.getHeader().getName());
                tempMetadata.setMetadataPackageVersion(metadataPackage.getHeader().getVersion().getVersionString());
                tempMetadata.setMetadataLanguage(metadata.getHeader().getLanguage());
                tempMetadata.setMavenPackageGroupId(apiModuleInfo.getGroupId());
                tempMetadata.setMavenPackageArtifactId(apiModuleInfo.getArtifactId());
                tempMetadata.setMavenPackageVersion(apiModuleInfo.getVersion());
                tempMetadata.setMavenPackageUrl(repoUrl);
                metadatas.add(tempMetadata);
            }

            packageWithMetadataInfo.setMetadatas(metadatas);

            String indexServerUrl = IndexServerManager.getInstance().getIndexServerUrl();
//            IndexServerConfiguration indexServer = IndexServerHelper.getInstance().getIndexServerConfigUration();
//            indexServer.setIP("localhost");
//            String url = "http://" + indexServer.getIP() + ":" + indexServer.getPort() + "/api/v1/metadataindex/mvn";
            restTemplate.postForObject(indexServerUrl, new HttpEntity<>(packageWithMetadataInfo, new HttpHeaders()), boolean.class);
        }
    }

    private ApiModuleInfo getApiModuleInfo(String apiPomPath) {
        try (FileInputStream fis = new FileInputStream(apiPomPath)) {
            MavenXpp3Reader reader = new MavenXpp3Reader();
            Model model = reader.read(fis);
            ApiModuleInfo apiModuleInfo = new ApiModuleInfo();
            //api模块继承父的groupid,artifactid,version,自己没有定义
            if (model.getGroupId() != null) {
                apiModuleInfo.setGroupId(model.getGroupId());
            } else {
                apiModuleInfo.setGroupId(model.getParent().getGroupId());
            }
            if (model.getArtifactId() != null) {
                apiModuleInfo.setArtifactId(model.getArtifactId());
            } else {
                apiModuleInfo.setArtifactId(model.getParent().getArtifactId());
            }
            if (model.getVersion() != null) {
                apiModuleInfo.setVersion(model.getVersion());
            } else {
                apiModuleInfo.setVersion(model.getParent().getVersion());
            }
            return apiModuleInfo;
        } catch (IOException | XmlPullParserException e) {
            log.error("获取[{}]模块信息失败", apiPomPath, e);
        }
        return null;
    }

    private void setRepoUrl(String codePom, String repoUrl, String repoId, boolean isSnapshot) {
        try (FileInputStream fis = new FileInputStream(codePom)) {
            MavenXpp3Reader reader = new MavenXpp3Reader();
            Model model = reader.read(fis);
            DistributionManagement distributionManagement = getDistributionManagement(repoUrl, repoId, isSnapshot);
            model.setDistributionManagement(distributionManagement);
            MavenXpp3Writer mavenXpp3Writer = new MavenXpp3Writer();
            FileOutputStream fos = new FileOutputStream(codePom);
            mavenXpp3Writer.write(fos, model);
            fos.close();
        } catch (IOException | XmlPullParserException e) {
            log.error("[{}]设置仓库路径[{}]失败", codePom, repoUrl, e);
        }
    }

    private boolean isJavaProjExist(String proPath) {
        //判断模板工程是否已创建。
        if (fileServiceImp.getProjectPath(proPath) != null) {
            String subpropath = fileServiceImp.getProjectPath(proPath);
            String fullPath = fileServiceImp.getCombinePath(proPath, subpropath);
            List<File> list = fileServiceImp.getAllFiles(fullPath);
            for (File file : list) {
                if (file.toString().endsWith("pom.xml")) {
                    return true;
                }
            }
        }
        return false;
    }

    private String getRepoUrl(String repoId) {
        String repoUrl = "";
        MetadataRepo metadataRepo = getRepoList();
        if (metadataRepo == null || metadataRepo.getRepoList() == null || metadataRepo.getRepoList().size() <= 0) {
            return null;
        }
        for (PackageSourceDto item : metadataRepo.getRepoList()) {
            if (item.getId().equals(repoId)) {
                repoUrl = item.getSourceUrl();
            }
        }

        return repoUrl;
    }

    private boolean addDependencyToMdproj(String groupid, String artifactid, String version, String mepath,
                                          String metadataPackageName) {
        //给对应的mdproj添加依赖信息
        metadataProject = metadataProjectCoreService.getMetadataProjInfo(mepath);
        MavenPackageRefs singlemavenPackageRefs = new MavenPackageRefs();
        singlemavenPackageRefs.setGroupId(groupid);
        singlemavenPackageRefs.setArtifactId(artifactid);
        singlemavenPackageRefs.setVersion(version);
        singlemavenPackageRefs.setMetadataPackageName(metadataPackageName);

        if (metadataProject.getMavenPackageRefs() == null) {
            List<MavenPackageRefs> list = new ArrayList<>();
            list.add(singlemavenPackageRefs);
            metadataProject.setMavenPackageRefs(list);
        } else {
            //不允许引用多个版本的相同包。
            List<MavenPackageRefs> mavenPackageRefs = metadataProject.getMavenPackageRefs();
            boolean isDependencyExits = false;
            for (MavenPackageRefs dep : mavenPackageRefs) {
                if (dep.getGroupId().equals(groupid) && dep.getArtifactId().equals(artifactid)) {
                    //如果groupId，artifactId相同，则更新版本号。
                    isDependencyExits = true;
                    dep.setVersion(version);
                    // 若maven引用中未记录对应元数据包名,则尝试从工作空间maven目录中查找对应元数据包,补充对应包名
                    if (!StringUtils.isEmpty(dep.getMetadataPackageName())) {
                        break;
                    }
                    if (StringUtils.isEmpty(metadataPackageName)) {
                        MdProjectDependencyNode node = MetadataPackageIndexService.getDependencyNodeByMaven(dep);
                        metadataPackageName = node == null? null : node.getMetadataPackageName();
                    }
                    if (StringUtils.isEmpty(metadataPackageName)) {
                        dep.setMetadataPackageName(metadataPackageName);
                    }
                    break;
                }
            }
            if (!isDependencyExits) {
                mavenPackageRefs.add(singlemavenPackageRefs);
            }
            metadataProject.setMavenPackageRefs(mavenPackageRefs);
        }
        //实体已更新,序列化到磁盘
        List<File> files = fileServiceImp.getAllFiles(mepath);
        File mdprojFile = null;
        for (File file : files) {
            if (".mdproj".equals(fileServiceImp.getExtension(file))) {
                mdprojFile = file;
                break;
            }
        }
        if (mdprojFile == null) {
            throw new LcmMetadataDevException(ErrorCodes.ECP_METADATA_DEV_0032, mepath);
        }
        Utils.writeValue(mdprojFile.getPath(), metadataProject);

        return true;
    }

    private boolean createPomAndDownloadMdproj(String groupid, String artifactid, String version, String path, Boolean forceUpdateFlag, String mavenPath) throws IOException {
        File pomFile = new File(fileServiceImp.getCombinePath(path, MavenUtils.pomFile));
        if (!pomFile.exists()) {
            if (pomFile.createNewFile()) {
                log.debug("创建下载pom.xml完成");
            }
        }
        FileOutputStream fileOutputStream = new FileOutputStream(pomFile);
        Model model = new Model();
        model.setArtifactId("com.inspur.edp");
        model.setGroupId("download-tools");
        model.setVersion("0.1.0-SNAPSHOT");
        model.setModelVersion("4.0.0");
        model.setPackaging("pom");
        List<Dependency> list = model.getDependencies();
        Dependency dependency = new Dependency();
        dependency.setArtifactId(artifactid);
        dependency.setGroupId(groupid);
        dependency.setVersion(version);
        dependency.setType("zip");
        list.add(dependency);
        model.setDependencies(list);
        MavenXpp3Writer mavenXpp3Writer = new MavenXpp3Writer();
        mavenXpp3Writer.write(fileOutputStream, model);
        fileOutputStream.close();
        downloadPath = fileServiceImp.getCombinePath(mavenPath, MavenUtils.tempFolder);

        //获取排除的artifact
        MetadataProject metadataProject = metadataProjectCoreService.getMetadataProjInfo(metadataProjectCoreService.getProjPath(path));
        StringBuilder excludeArtifactIds = new StringBuilder();
        if (metadataProject.getMavenPackageRefs() != null && metadataProject.getMavenPackageRefs().size() > 0) {
            for (MavenPackageRefs mavenPackageRef : metadataProject.getMavenPackageRefs()) {
                if (!mavenPackageRef.getArtifactId().equals(artifactid)) {
                    excludeArtifactIds.append(mavenPackageRef.getArtifactId()).append(",");
                }
            }
        }
        if (excludeArtifactIds.length() > 0) {
            excludeArtifactIds = new StringBuilder(excludeArtifactIds.substring(0, excludeArtifactIds.length() - 1));
        }

        String mvnCommand = String.format(" dependency:copy-dependencies -DoutputDirectory=%s -DincludeTypes=zip -DexcludeArtifactIds=%s -Dmdep.copyPom", downloadPath, excludeArtifactIds);
        mvnCommand = forceUpdateFlag ? mvnCommand + " -U" : mvnCommand;
        //拷贝依赖
        mavenInvoker.execute(path, mvnCommand, mavenPath);
        return true;
    }

    private void checkModule(String codePath, String module) {
        String srcPath = codePath + File.separator + module + File.separator + "pom.xml";
        if (!fileServiceImp.isFileExist(srcPath)) {
            throw new LcmMetadataDevException(ErrorCodes.ECP_METADATA_DEV_0033, module, srcPath);
        }
    }

    private MetadataPackageHeader handleMetadataPackageName(String packName) {
        MetadataPackageHeader packageHeader = new MetadataPackageHeader();
        packageHeader.setName(packName.replace(".mdpkg", ""));
        packageHeader.setVersion(new MetadataPackageVersion("1.0.0"));

        return packageHeader;
    }

    private void createPomForDeploy(ApiModuleInfo info, List<MavenPackageRefs> refs, String pomPath, String repoUrl, String repoId, String dependencyVersion) throws IOException {
        File pomDir = new File(pomPath);
        if (!pomDir.exists()) {
            if (pomDir.mkdir()) {
                log.debug("创建打包目录完成");
            }
        }
        File pom_file = new File(fileServiceImp.getCombinePath(pomDir.toString(), MavenUtils.pomFile));
        if (!pom_file.exists()) {
            if (pom_file.createNewFile()) {
                log.debug("创建打包pom.xml完成");
            }
        }
        try (FileOutputStream fileOutputStream = new FileOutputStream(pom_file)) {
            Model model = new Model();
            //构造父pom信息
            Parent parent = new Parent();
            parent.setArtifactId("metadata-parent");
            parent.setGroupId("com.inspur.edp");
            boolean isSnotshot = apiModuleInfo.getVersion().endsWith(MavenUtils.snapShot);
            parent.setVersion("0.1.0");
            model.setParent(parent);
            model.setArtifactId(info.getArtifactId());
            model.setGroupId(info.getGroupId());
            model.setVersion("m" + info.getVersion());
            model.setModelVersion("4.0.0");
            model.setPackaging("metadata-pack");
            DistributionManagement distributionManagement = getDistributionManagement(repoUrl, repoId, isSnotshot);
            model.setDistributionManagement(distributionManagement);
            List<Dependency> list = model.getDependencies();
            if (refs != null && refs.size() > 0) {
                refs.forEach(ref -> {
                    Dependency dependency = new Dependency();
                    dependency.setGroupId(ref.getGroupId());
                    dependency.setArtifactId(ref.getArtifactId());
                    if (dependencyVersion != null && ref.getVersion().endsWith(MavenUtils.snapShot)) {

                        dependency.setVersion("m" + dependencyVersion);
                    } else {
                        dependency.setVersion(ref.getVersion());
                    }
                    dependency.setType("zip");
                    list.add(dependency);
                });
            }
            //配置插件，必须配置lcm-metadata-build-maven-plugin

            model.setDependencies(list);
            MavenXpp3Writer mavenXpp3Writer = new MavenXpp3Writer();
            mavenXpp3Writer.write(fileOutputStream, model);
        } catch (IOException e) {
            log.error("生成打包pom[{}]失败", pom_file, e);
        }
    }

    private DistributionManagement getDistributionManagement(String repoUrl, String repoId, boolean isSnotshot) {
        DistributionManagement distributionManagement = new DistributionManagement();
        DeploymentRepository deploymentRepository = new DeploymentRepository();
        deploymentRepository.setId(repoId);
        deploymentRepository.setUrl(repoUrl);
        if (isSnotshot) {
            distributionManagement.setSnapshotRepository(deploymentRepository);
        } else {
            distributionManagement.setRepository(deploymentRepository);
        }
        return distributionManagement;
    }

    private boolean createSrcDir(String mdpkgPath) {
        String resDir = mdpkgPath + File.separator + MavenUtils.resourcesDir;
        File resourceFile = new File(resDir);
        return resourceFile.mkdirs();
    }

    private void afterCompile(String absolutePath) {
        List<String> types = new ArrayList<>();
        types.add("comp");
        metadataProjectCoreService.setSourceDataModifiedTime(absolutePath, types);
    }

    private void extractMd(String libPath, String mavenPath) {
        lock.lock();
        try {
            // 获取lib下所有的元数据包，解压到/projects/maven下
            List<File> allFiles = fileServiceImp.getAllFiles(libPath);
            downloadMdpkgPaths = new ArrayList<>();
            allFiles.stream().parallel().forEach(file -> {
                String desMetadataDir;
                String exactGroupId = getGroupId(file);
                // 解压元数据包
                if (Utils.getZipSuffix().equals(fileServiceImp.getExtension(file))) {
                    try(ZipFile zf = new ZipFile(file);
                        InputStream  in = new BufferedInputStream(new FileInputStream(file));
                        ZipInputStream zin = new ZipInputStream(in, StandardCharsets.UTF_8)) {

                        ZipEntry ze;
                        InputStream is = null;
                        while ((ze = zin.getNextEntry()) != null) {
                            try {
                                if (Utils.getMetadataPackageExtension().equals(fileServiceImp.getExtension(ze.toString()))) {
                                    String fileName = ze.getName();
                                    is = zf.getInputStream(ze);

                                    String fileNameWithoutExt = fileServiceImp.getFileNameWithoutExtension(file);
                                    desMetadataDir = mavenPath + File.separator + exactGroupId + "-" + fileNameWithoutExt;
                                    String outputFilePath = desMetadataDir + File.separator + fileName;
                                    downloadMdpkgPaths.add(outputFilePath);
                                    // 如果是已存在的正式版，则不需要再解压到maven文件夹
                                    if (isReleaseMdpkgExists(desMetadataDir)) {
                                        return;
                                    }

                                    if (!fileServiceImp.isDirectoryExist(desMetadataDir)) {
                                        fileServiceImp.createDirectory(desMetadataDir);
                                    }
                                    String pomFileName = fileNameWithoutExt + Utils.getPomSuffix();
                                    fileServiceImp.fileCopy(libPath + File.separator + pomFileName, desMetadataDir + File.separator + pomFileName);
                                    File outputFile = new File(outputFilePath);
                                    try(OutputStream outputStream = new FileOutputStream(outputFile)){
                                        int len;
                                        while ((len = is.read()) != -1) {
                                            outputStream.write(len);
                                        }
                                    }
                                }
                            } catch (IOException e) {
                                log.error(e.toString());
                            } finally {
                                if (is != null) {
                                    is.close();
                                }

                            }
                        }
                    } catch (IOException e) {
                        log.error("读取压缩包[{}]内容失败", file.getPath());
                    }
                }
            });
        } catch (Exception e) {
            throw new LcmMetadataDevException(e, ErrorCodes.ECP_METADATA_DEV_0034, libPath);
        } finally {
            lock.unlock();
        }
    }

    private boolean isReleaseMdpkgExists(String desMetadataDir) {
        return !desMetadataDir.endsWith(Utils.getVersionSuffix()) && fileServiceImp.getAllFiles(desMetadataDir).size() == 2;
    }

    private String getGroupId(File file) {
        PomManager pomManager = new PomManager();
        String groupId = null;
        String pomPath = file.getPath().replace(".zip", ".pom");
        if (fileServiceImp.isFileExist(pomPath)) {
            Model model = pomManager.getModel(pomPath);
            if (model != null) {
                groupId = model.getGroupId();
            }
        }
        return groupId;
    }

    private void copyDependencies(String pomDirPath, String mavenPath, String tempPath, boolean forceUpdateFlag) {
        final MavenCommandGenerator mavenCommandGenerator = new MavenCommandGenerator();
        mavenCommandGenerator.setOutputDirectory(tempPath);
        mavenCommandGenerator.setIncludeTypes(PackageType.zip.toString());
        mavenCommandGenerator.setCopyPom(true);
        mavenCommandGenerator.setForceUpdate(forceUpdateFlag);
        final String mavenCommand = mavenCommandGenerator.generateCopydependencies();
        mavenInvoker.execute(pomDirPath, mavenCommand, mavenPath);
    }

    private void updateMetadataIndexWithProcessMode(String mdpkgName, String mdpkgDir, String repoUrl, ApiModuleInfo apiModuleInfo, String processMode) {
        final MavenDeploymentForMdpkgManager mavenDeploymentForMdpkgManager = new MavenDeploymentForMdpkgManager();
        Model sourceModel = new Model();
        sourceModel.setGroupId(apiModuleInfo.getGroupId());
        sourceModel.setArtifactId(apiModuleInfo.getArtifactId());
        sourceModel.setVersion(apiModuleInfo.getVersion());
        mavenDeploymentForMdpkgManager.updateMetadataIndex(mdpkgName, mdpkgDir, repoUrl, sourceModel, processMode);
    }

    private void changeRefProcessModeWithArtifactInfo(String absolutePath, String mdpkgName, ProcessMode processMode, String groupId, String artifactId) {
        // 更改mdproj中的信息
        updateMetadataPackageHeader(absolutePath, mdpkgName, processMode);

        // 删除api.pom或者comp.pom中的引用
        deleteDependency(absolutePath, groupId, artifactId);
    }

    private void updateMetadataPackageHeader(String absolutePath, String mdpkgName, ProcessMode processMode) {
        // 更改mdproj中的信息
        MetadataProject metadataProjInfo = metadataProjectCoreService.getMetadataProjInfo(absolutePath);
        if (metadataProjInfo == null) {
            throw new LcmMetadataDevException(ErrorCodes.ECP_METADATA_DEV_0004, absolutePath);
        }
        if (CollectionUtils.isEmpty(metadataProjInfo.getMetadataPackageRefs())) {
            throw new LcmMetadataDevException(ErrorCodes.ECP_METADATA_DEV_0029, absolutePath);
        }
        MetadataPackageHeader packageHeader = metadataProjInfo.getMetadataPackageRefs().stream().filter(ref -> ref.getName().equalsIgnoreCase(mdpkgName)).findFirst().orElse(null);
        if (packageHeader == null) {
            throw new LcmMetadataDevException(ErrorCodes.ECP_METADATA_DEV_0030, mdpkgName);
        }
        if (processMode.equals(packageHeader.getProcessMode())) {
            throw new LcmMetadataDevException(ErrorCodes.ECP_METADATA_DEV_0031, processMode.getDesc());
        }
        packageHeader.setProcessMode(processMode);
        metadataProjectCoreService.updateMetadataProject(absolutePath, metadataProjInfo);
    }

    private void deleteDependency(String absolutePath, String groupId, String artifactId) {
        PomManager pomManager = new PomManager();
        Dependency dependency = new Dependency();
        dependency.setGroupId(groupId);
        dependency.setArtifactId(artifactId);
        pomManager.deleteDependency(absolutePath, PomManager.API, dependency);
        pomManager.deleteDependency(absolutePath, PomManager.COMP, dependency);
    }
}
